﻿using System;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Concurrent;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //LinqOne();

            //SampleClass s = new SampleClass();
            //Type type = s.GetType();
            //Author au = (Author)type.GetCustomAttributes(false)[0];
            //Console.WriteLine(au.version);
            try
            {
                TestLinqSpeed();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            Console.ReadLine();
        }

        static void LinqOne()
        {
            Func<int, bool> myFunc = x => x == 5;
            Console.WriteLine(myFunc(4));

            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
            int oddNumbers = numbers.Count(n => n % 2 == 1);
            Console.WriteLine(oddNumbers);
        }

        static void TestLinqSpeed()
        {
            int MACRO = 10000;
            //List<User> lst = new List<User>();
            //User u = null;
            var w = Stopwatch.StartNew();
            //for (int i = 0; i < 10000000; i++)
            //{
            //    int idnum = new Random().Next(0, 10000000);
            //    u = new User();
            //    u.UserName = "Martin" + idnum;
            //    u.Id = idnum;
            //    u.Gender = i % 2 == 0 ? "男" : "女";
            //    u.Birthday = DateTime.Now;
            //    lst.Add(u);
            //    if ((i + 1) % 1000000 == 0)
            //    {
            //        Console.WriteLine("Creating Data ...............................{0}%", (i + 1) / 100000);
            //    }
            //}
            //Console.WriteLine(w.Elapsed.ToString());
            //Console.WriteLine();
           // List<User> lst = new List<User>();     
            ConcurrentStack<User> lst = new ConcurrentStack<User>();
            Parallel.For<User>(0, MACRO, () => new User(), (i, loopState, uu) =>
            {
                //Console.WriteLine("i ={0} ",i.ToString());
                //list = new List<User>();
                int idnum = new Random().Next(0, MACRO);
                uu = new User();
                uu.UserName = "Martin" + idnum;
                uu.Id = idnum;
                uu.Gender = i % 2 == 0 ? "男" : "女";
                uu.Birthday = DateTime.Now;
               // list.Add(u);
                //if ((i + 1)*100 % MACRO == 0)
                //{
                //    Console.WriteLine("Creating Data ...............................{0}%", (i + 1) / MACRO*100);
                //}
                lst.Push(uu);
                return uu;
            }, (x) => 
            {
                //Console.WriteLine("Type of creating is {0},count = {1}",x.GetType().ToString(), x.UserName);
                //Interlocked.Exchange<List<User>>(ref lst, x);
               // lst.Add(x);
               // Console.WriteLine("Result count = {0}",lst.Count);
            }
            );
            Console.WriteLine("Result count = {0}", lst.Count);
            Console.WriteLine(w.Elapsed.ToString());
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
           
           

            //int index = new Random().Next(10000000);
            //string name = lst[index].UserName;
            //int id = lst[index].Id;
            //DateTime t1 = DateTime.Now;
            //var watch = Stopwatch.StartNew();
            //foreach (User u1 in lst)
            //{
            //    if (u1.Id == id && u1.UserName == name)
            //    {
            //        Console.WriteLine("Foreach searching time:" + (DateTime.Now - t1).ToString());
            //        break;
            //    }
            //}
            //DateTime t2 = DateTime.Now;
            //var us = (from user in lst
            //          where user.UserName == name && user.Id == id
            //          select user).First<User>();
            //Console.WriteLine("Linq searching time:" + (DateTime.Now - t2).ToString());

            //DateTime t3 = DateTime.Now;
            //var us2 = lst.Find(ur => (ur.UserName == name && ur.Id == id));
            //Console.WriteLine("Lumda Expression searching time:" + (DateTime.Now - t3).ToString());
            //// Console.WriteLine(watch.Elapsed.Seconds+"."+watch.Elapsed.Milliseconds);
            //watch.Restart();
            //bool _get = false;
            //User uf = new User();
            //uf.UserName = string.Empty;
            //DateTime t4 = DateTime.Now;
            //Parallel.For(0, 10000000, i =>
            //{
            //    lock (uf)
            //    {
            //        if (uf.UserName == string.Empty)
            //        {
            //            if (lst[i].UserName == name && lst[i].Id == id)
            //            {
            //                uf.UserName = name;
            //                Console.WriteLine("Parallet searching time:" + (DateTime.Now - t4).ToString());
            //                //Console.WriteLine(watch.Elapsed.Seconds + "." + watch.Elapsed.Milliseconds);
            //            }
            //        }
            //    }

            //});
            //watch.Stop();
        }

        public class User
        {
            int _id;

            public int Id
            {
                get { return _id; }
                set { _id = value; }
            }
            string _userName;

            public string UserName
            {
                get { return _userName; }
                set { _userName = value; }
            }
            string _gender;

            public string Gender
            {
                get { return _gender; }
                set { _gender = value; }
            }
            int _age;

            public int Age
            {
                get { return _age; }
                set { _age = value; }
            }
            DateTime _birthday;

            public DateTime Birthday
            {
                get { return _birthday; }
                set { _birthday = value; }
            }
        }
    }

    [System.AttributeUsage(System.AttributeTargets.Class |
                       System.AttributeTargets.Struct)]
    public class Author : System.Attribute
    {
        private string name;
        public double version;
        public Author(string name)
        {
            this.name = name;
            version = 1.0;
        }
    }
    [Author("H. Ackerman", version = 1.1)]
    class SampleClass
    {
        // H. Ackerman's code goes here...
        public SampleClass()
        {

        }
    }

}
